package compiler;


import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.io.PrintStream;

import compiler.ast.ASTRoot;
import compiler.dot.GraphHelper;
import compiler.parser.Parser;
import compiler.scanner.Scanner;
import compiler.tac.SSAPRE;
import compiler.tac.ThreeAddressCode;


public class CompilerSNUPL {
	public static void main(String[] arg) {
		InputStream in = null;
		PrintStream outC = null;
		PrintStream outG = null;

		try {
			if (arg.length == 0) {
				System.out.print(">");
				in = System.in;
				outC = System.out;
				outG = System.out;
			} else if (arg.length == 1) {
				in = new FileInputStream(arg[0]);
				outC = System.out;
				outG = System.out;
			} else if (arg.length == 2) {
				in = new FileInputStream(arg[0]);
				outC = new PrintStream(new File(arg[1]));
				outG = System.out;
			} else /* arg.length >= 3 */{
				in = new FileInputStream(arg[0]);
				outC = new PrintStream(new File(arg[1]));
				outG = new PrintStream(new File(arg[2]));
			}
		} catch (FileNotFoundException e) {
			System.out.println("Error: " + e.getMessage());
			System.exit(0);
		}
		
		ASTRoot ast = null;
		try {
			Scanner scanner = new Scanner(in);
			Parser parser = new Parser(scanner);

			ast = parser.parse();
			
			// print AST
			ast.printAST(outG);
			
			ThreeAddressCode tac = ast.toThreeAddressCode();

			// print CFG
			GraphHelper graph = new GraphHelper(outG, "beforeSSA");
			tac.printCFG(graph);
			graph.close();
			
			tac.buildDominatorTree();

			tac.calDomF();

			// print DT
			graph = new GraphHelper(outG, "DT");
			tac.printDT(graph);
			graph.close();
			
			tac.toSSAForm();
			
			// print CFG of SSA form
			graph = new GraphHelper(outG, "afterSSA");
			tac.printCFG(graph);
			graph.close();
			
			SSAPRE ssapre = new SSAPRE();
			ssapre.doSSAPRE(tac);
			
			// print CFG after SSAPRE
			graph = new GraphHelper(outG, "afterSSAPRE");
			tac.printCFG(graph);
			graph.close();
			
			// print Three-address code
			tac.printTAC(outC);
			
		} catch (CompileException e) {
			System.out.println(e.getMessage());
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}
